

#include "sheet.h"


/**
	buf : 图层
	bxsize ,bysize : 图层大小
	vx0 ,vy0 在屏幕的坐标位置
	col_inv : 透明图层的颜色
	height : 所处的高度
	flags: 存放各种设定信息 
*/


SHEET_MANAGEMENT * shtman_init (MEMORY_MANAGEMENT * memman ,unsigned char * vram ,int xsize ,int ysize) { 
	int  i ;
	SHEET_MANAGEMENT * shtman ;
	shtman = memman_alloc_4k (memman ,sizeof (SHEET_MANAGEMENT)) ;
	shtman->xsize = xsize ;
	shtman->ysize = ysize ;
	shtman->top = -1 ;
	shtman->vram = vram ;
	for (i=0 ; i <MAX_SHEET_SIZE ; i++) { 
		shtman->sheets0[i].flags = 0 ; /**将所有图层标记为未使用*/
		shtman->sheets0[i].shtman = shtman ;
	}
	return shtman ;
}

SHEET * sheet_alloc (SHEET_MANAGEMENT * shtman) { 
	SHEET * sht  ;
	int i  ; 
	for (i= 0 ; i < MAX_SHEET_SIZE ;i++) { 
		if (shtman->sheets0[i].flags ==0 ) {
			sht = &shtman->sheets0[i] ;  
			sht->flags =SHEET_FLAG_USED ;
			sht->height =-1 ;/**表示隐藏*/
			return sht ;
		}
	}
	return  0 ; /*表示所有MAX_SHEET_SIZE个图层都在使用 ，无法再alloc*/
}
//设置图层
void sheet_setbuf (SHEET * sht ,char * buf ,int bxsize ,int bysize ,int col_inv) { 
	sht->buf = buf ;
	sht->bxsize = bxsize ;
	sht->bysize = bysize ;
	sht->col_inv =col_inv ;
	return ;
}

//修改某个sheet的高度
void sheet_updown (SHEET * sht ,int height) { 
	SHEET_MANAGEMENT * shtman  = sht->shtman ;
	int oldheight = sht->height ;
	int i ;
	/***指定高度过高或过低时进行修正 */
	if (height > shtman->top+1) {  
		height = shtman->top+1 ;
	}
	if (height <-1) { 
		height =-1 ;
	}
	sht->height = height ; //设定高度

	/*对shtman中的ascsheets[]进行重排列*/
	if (height < oldheight){ //比以前低 
		if (height >=0){  
			for (i= oldheight-1 ; i >=height ; i--){  //右移
				shtman->ascsheets[i]->height = i+1 ; 
				shtman->ascsheets[i+1] = shtman->ascsheets[i] ;
			}
			shtman->ascsheets[height] = sht ;
		}
		else {  //height <0 ,隐藏 左移 
			for (i = oldheight+1 ; i<=shtman->top ;i++ ){ 
				shtman->ascsheets[i]->height = i-1 ;
				shtman->ascsheets[i-1] = shtman->ascsheets[i] ;
			}
			shtman->top --;
		}
		sheet_refresh_bysht (sht) ;
	}else if (height > oldheight ) { //现在的height比以前高 
		if (oldheight >=0 ){
			if (height > shtman->top) { 
				for (i = oldheight+1; i<=shtman->top ; i++) {  //把oldheight 到height -1 到 之间的图层向左移
					shtman->ascsheets[i]->height = i-1 ;
					shtman->ascsheets[i-1] = shtman->ascsheets[i] ;
				}	
			}else { 
				for (i =oldheight+1 ;i<=height ;i++){ 
					shtman->ascsheets[i]->height = i-1 ;
					shtman->ascsheets[i-1] = shtman->ascsheets[i] ;
				}
			}
			shtman->ascsheets[height] = sht;
			
		}else {  //从隐藏转为显示  原height 到top的图层要右移
			for (i = shtman->top ;i >=height ; i-- ){ 
				shtman->ascsheets[i]->height = i+1 ; 
				shtman->ascsheets[i+1] = shtman->ascsheets[i] ;
			}
			shtman->ascsheets[height] = sht;
			shtman->top ++ ;
		}
		sheet_refresh_bysht (sht) ;
	}
	 //如果oldheight = height ,我们不进行sheet_refresh 
	return ;
}

//
void sheet_refresh_bysht ( SHEET * sht ) { 
	SHEET_MANAGEMENT * shtman  = sht->shtman ;
	sheet_refresh_between (shtman ,sht->vx0 ,sht->vy0 ,sht->vx0 + sht->bxsize-1 ,sht->vy0 + sht->bysize-1,sht->height ,shtman->top) ;
}
//刷新一个图层的局部位置 （4个坐标指图层内的坐标 ，而不是主屏幕上的坐标）
void sheet_refresh_bysht2 (SHEET *sht ,int x0,int y0 ,int x1,int y1) { 
	SHEET_MANAGEMENT * shtman  = sht->shtman ;
	sheet_refresh_between (shtman ,sht->vx0 +x0,sht->vy0 +y0 ,sht->vx0+x1 ,sht->vy0+y1,sht->height ,shtman->top) ;	
} 

//刷新在h0 - h1高度之间的图层
void sheet_refresh_between (SHEET_MANAGEMENT * shtman ,int vx0 ,int vy0 ,int vx1 ,int vy1 ,int h0 ,int h1) { 
	int h,i,j  ,bx0 ,by0 ,bx1 ,by1 ; //最终重叠部分的坐标 
		int vx20 ,vx21 ,vy20 ,vy21 ; //当前sheet的坐标
		SHEET * sht ; 
		unsigned char *buf ,c, *vram = shtman->vram;

		/*如果画面超出了图像范围 ，需要修正*/
		if (vx0<0) vx0 = 0 ;
		if (vx1>=shtman->xsize) vx1 =shtman->xsize-1 ;
		if (vy0<0) vy0 = 0 ;
		if (vy1>=shtman->ysize) vy1 =shtman->ysize-1 ; 

		//判断h0 -h1 的范围
		if (h0 < 0) h0 = 0 ;
		if (h1 > shtman->top ) h1 = shtman->top ;
		for (h = h0 ;h <=h1 ; h++){ 
			sht = shtman->ascsheets[h] ; 
			buf = sht->buf ; 

			vx20  = sht->vx0 ; 
			vx21  = vx20 + sht->bxsize-1 ;
			vy20  = sht->vy0 ;
			vy21  = vy20 + sht->bysize-1 ;
			if (vx20 > vx1 || vx21 < vx0 ){ //不重叠判断
				continue ; 
			} 
			if (vy20 > vy1 || vy21 < vy0) { 
				continue ; 
			} 
			bx0 = vx0 >vx20 ? vx0 : vx20 ; //取大
			by0 = vy0 >vy20 ? vy0 : vy20 ; //取大
			bx1 = vx1 >vx21 ? vx21: vx1 ;//取小
			by1 = vy1 >vy21 ? vy21: vy1 ;//取小
			for (i =by0;i <=by1 ;i ++){ 
				for (j=bx0; j <=bx1 ;j ++) { 
					c = buf[(i-vy20) *sht->bxsize +j -vx20] ; //i和j是在vram中的位置 ，要换算成在buf中的位置
					if (c != sht->col_inv) {  //如果不是透明色
						vram[i * shtman->xsize + j] = c ;
					}
				}
			}
		}
}

//局部刷新每个图层和坐标(vx0,vy0) ,(vx1,vy1)的重叠部分
void sheet_refresh (SHEET_MANAGEMENT * shtman ,int vx0 ,int vy0 ,int vx1 ,int vy1) { 

		sheet_refresh_between (shtman ,vx0, vy0 , vx1 , vy1 ,0, shtman->top) ;
		
}
/*
void sheet_refresh(SHEET_MANAGEMENT *ctl, int vx0, int vy0, int vx1, int vy1)
{
	int h, bx, by, vx, vy, bx0, by0, bx1, by1;
	unsigned char *buf, c, *vram = ctl->vram;
	 SHEET *sht;
	for (h = 0; h <= ctl->top; h++) {
		sht = ctl->ascsheets[h];
		buf = sht->buf;
		
		bx0 = vx0 - sht->vx0;
		by0 = vy0 - sht->vy0;
		bx1 = vx1 - sht->vx0;
		by1 = vy1 - sht->vy0;
		if (bx0 < 0) { bx0 = 0; }
		if (by0 < 0) { by0 = 0; }
		if (bx1 > sht->bxsize) { bx1 = sht->bxsize; }
		if (by1 > sht->bysize) { by1 = sht->bysize; }
		for (by = by0; by < by1; by++) {
			vy = sht->vy0 + by;
			for (bx = bx0; bx < bx1; bx++) {
				vx = sht->vx0 + bx;
				c = buf[by * sht->bxsize + bx];
				if (c != sht->col_inv) {
					vram[vy * ctl->xsize + vx] = c;
				}
			}
		}
	}
	return;
}
*/
void sheet_slide (SHEET * sht , int vx0 ,int vy0 ){ 
	SHEET_MANAGEMENT * shtman  = sht->shtman ;
	int old_vx0 = sht->vx0 , old_vy0 = sht->vy0 ;
	sht->vx0 = vx0 ;
	sht->vy0 = vy0 ;
	if (sht->height >=0) { 
		sheet_refresh_between (shtman ,vx0 ,vy0 ,vx0 +sht->bxsize-1 ,vy0 +sht->bysize-1,0 ,shtman->top) ;
		sheet_refresh_between (shtman ,old_vx0 ,old_vy0 ,old_vx0 +sht->bxsize-1 ,old_vy0 +sht->bysize-1,0 ,shtman->top) ;
	}
}

void sheet_free (SHEET * sht) { 
	if (sht->height >=0 ){ 
		sheet_updown(sht, -1);
	}
	sht->flags = 0 ;
	return  ;
}  
